/*
 * 文件名:ServiceFacade.java
 * 创建时间:2009-03-10
 * 版本:1.0
 * 版权所有:杨涛
 */
package com.yangtao.framework.aop;

import com.yangtao.framework.common.SystemConstant;
import com.yangtao.framework.service.BussinessException;
import com.yangtao.framework.web.struts2.BaseModel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.springframework.dao.CannotAcquireLockException;
import org.springframework.dao.OptimisticLockingFailureException;

/**
 * springAOP的一个切面bean，集中处理业务逻辑层的异常以及日志记录
 *
 * @author 杨涛
 * @创建时间:2009-03-10
 * @修改者:
 * @修改时间:
 * @version: 1.0
 */
public class ServiceAop {
	/* 日志记录 */
	protected final Log logger = LogFactory.getLog(getClass());

	/**
	 * 在切入点织入的增强处理，详细配置请参照applicationContext.xml中对切入点的定义
	 *
	 * @param jp 目标增强点的代理对象
	 * @return 目标方法的执行结果
	 * @throws Throwable 异常
	 */
	public Object execute(ProceedingJoinPoint jp) throws Throwable {
		/* 代理目标方法的返回值 */
		Object ret = null;
		/* 代理目标方法的参数 */
		Object[] args = jp.getArgs();
		String fullName = null;
		long start = System.currentTimeMillis();
		try {
			/* 取得代理对象的详细信息 */
			Signature s = jp.getSignature();
			/* 代理对象的方法名 */
			String methodName = s.getName();
			/**
			 * 以下代码通过标记在接口上的Annotation取得特定信息 TODO 将反射后的方法缓存
			 */
			// Object[] argTypes = new Object[args.length];
			// for(int i= 0;i<args.length;i++){
			// argTypes[i] = args[i].getClass();
			// }
			// Method m = s.getDeclaringType().getMethod(methodName,
			// argTypes);
			// for(Annotation a: m.getAnnotations()){
			// if(a instanceof BizLog){
			//
			// }
			// }
			/* 代理对象的类名 */
			String className = s.getDeclaringTypeName();
			s.getDeclaringTypeName();
			/* 线程名 + 代理对象类名+冒号+代理对象方法名 */
			fullName = "线程:" + Thread.currentThread().getName() + " 类:"
					+ className.substring(className.lastIndexOf(".") + 1)
					+ " 方法:" + methodName;
			// 记录日志
			logger.info(fullName + "**********开始执行**********");
			// 执行代理对象的方法
			ret = jp.proceed(args);
			// 异常处理
		} catch (Exception e) {
			if (e instanceof BussinessException) {
				// 出现业务异常，返回原有业务参数
				logger.info(fullName + "**********出现业务异常**********");
				logger.error(e.getMessage(), e);
				addError(e.getMessage(), args);
			} else if (e instanceof CannotAcquireLockException) {
				logger.info(fullName + "**********出现数据库锁定异常**********");
				logger.error(e.getMessage(), e);
				addError(SystemConstant.LOCK_ERROR, args);
			} else if (e instanceof OptimisticLockingFailureException) {
				logger.info(fullName + "**********数据冲突异常**********");
				logger.error(e.getMessage(), e);
				addError(SystemConstant.CONFLICT_ERROR, args);
			} else {
				logger.info(fullName + "**********出现异常**********");
				logger.error(e.getMessage(), e);
				e.printStackTrace();
				addError(SystemConstant.SYSTEM_ERROR, args);
				throw e;
			}
		}
		long end = System.currentTimeMillis();
		logger.info(fullName + "**********执行完毕**********耗时:[" + (end - start) + "] 毫秒");
		return ret;
	}

	/**
	 * 增加错误消息
	 *
	 * @param messageKey 错误消息key
	 * @param args       调用方法参数
	 */
	private void addError(String messageKey, Object[] args) {
		if (args.length > 0) {
			if (args[0] instanceof BaseModel) {
				BaseModel model = (BaseModel) args[0];
				model.addError(messageKey);
			}
		}
	}
}
